import AsyncStorage from "@react-native-community/async-storage";
import GitHubTrending from "GitHubTrending/trending/GitHubTrending";

// 是哪一种请求
export const FLAG_STORAGE = {flag_popular: 'popular', flag_trending: 'trending'};

const token = 'yes';
/**
 * 离线缓存，将请求的网络数据存储到本地，保存一段时间
 * 请求数据时优先请求本地数据
 */
export default class DataStore {
  /**
   * 检查timestamp是否在有效期
   * @param timeStamp
   * @returns {boolean}
   */
  static checkTimestampValid(timeStamp) {
    // 当前时间
    const currentDate = new Date();
    const targetDate = new Date();
    // 本地数据存入时间
    targetDate.setTime(timeStamp);
    if (currentDate.getMonth() !== targetDate.getMonth()) return false;
    if (currentDate.getDate() !== targetDate.getDate()) return false;
    if (currentDate.getHours() - targetDate.getHours() > 4) return false;
    return true
  }

  /**
   * 包装数据，记录数据存入本地时间
   * @param data
   * @returns {{timeStamp: *, data: *}}
   * @private
   */
  _wrapData(data) {
    return {data: data, timeStamp: new Date().getTime()}
  }

  /**
   * 获取数据
   * @param url
   * @param flag
   * @returns {Promise<unknown>}
   */
  fetchData(url, flag) {
    return new Promise((resolve, reject) => {
      // 先获取本地数据
      this.fetchLocalData(url)
        .then(wrapData => {  // 获取本地数据成功
          // 如果本地有数据且未过期
          if (wrapData && DataStore.checkTimestampValid(wrapData.timeStamp)) {
            resolve(wrapData)
          } else {
            // 如果本地没有数据或者数据已过期，则获取网络数据
            this.fetchNetData(url, flag)
              .then(data => {
                resolve(this._wrapData(data))
              })
              .catch(err => {
                reject(err)
              })
          }
        })
        .catch(error => {  // 获取本地数据失败
          this.fetchNetData(url, flag)
            .then(data => {
              resolve(this._wrapData(data))
            })
            .catch(err => {
              reject(err)
            })
        })
    })
  }

  /**
   * 将数据保存到本地
   * @param url
   * @param data
   * @param callback
   */
  saveData(url, data, callback) {
    if (!url || !data) return
    AsyncStorage.setItem(url, JSON.stringify(this._wrapData(data)), callback)
  }

  /**
   * 获取本地数据
   * @param url
   * @returns {Promise<unknown>}
   */
  fetchLocalData(url) {
    return new Promise((resolve, reject) => {
      AsyncStorage.getItem(url, (error, result) => {
        if (!error) {  //获取本地数据没有错误
          try {
            resolve(JSON.parse(result))
          } catch (err) {
            reject(err);
            console.error(err)
          }
        } else {  //获取本地数据有错误
          reject(error);
          console.error(error)
        }
      })
    })
  }

  /**
   * 从网络获取数据保存到本地
   * @param url
   * @param flag
   * @returns {Promise<unknown>}
   */
  fetchNetData(url, flag) {
    return new Promise((resolve, reject) => {
      // 如果不是trending模块请求数据
      if (flag !== FLAG_STORAGE.flag_trending) {
        // 通过fetch获取数据
        fetch(url)
          .then(response => {
            if (response.ok) {
              return response.json()  //返回json格式数据
            }
            throw new Error('Network response was not ok.')
          })
          .then(value => {
            this.saveData(url, value);  //将网络数据保存到本地
            resolve(value)
          })
          .catch(err => {
            reject(err)
          })
      } else {
        // 通过GitHubTrending获取趋势数据
        new GitHubTrending(token).fetchTrending(url)
          .then(items => {
            if(!items){
              throw new Error('responseData is null.')
            }
            this.saveData(url,items);
            resolve(items)
          })
          .catch(error => {
            reject(error)
          })
      }


    })
  }
}
